/* 
 * File:   OperacionSincronizacionArchivosNuevos.cpp
 * Author: maximiliano
 * 
 * Created on 15 de junio de 2013, 10:41
 */

#include "client_OperacionSincronizacionArchivosNuevos.h"
#include "client_OperacionCargaArchivo.h"
#include "client_OperacionDescargaArchivo.h"
#include "common_TokenFactory.h"

using namespace TP::Comunicacion;
using namespace TP::Operaciones;

OperacionSincronizacionArchivosNuevos::OperacionSincronizacionArchivosNuevos(const uint32_t &pToken, Repositorio **pRepositorioLocal, Repositorio **pRepositorioServidor, FileServiceProxy* pFileService) : OperacionSecuencial(pToken) {
    _repositorioLocal = pRepositorioLocal;
    _repositorioServidor = pRepositorioServidor;
    _fileService = pFileService;
    this->setFinalizada(true);
}

OperacionSincronizacionArchivosNuevos::~OperacionSincronizacionArchivosNuevos() {}

void OperacionSincronizacionArchivosNuevos::ejecutar(){
    
    /* Se calcula el esquema de trabajo.  Esto es, las operaciones que tiene que
     * ejecutar el secuencia la operacion de sincronizacion a fin de llevar
     * a cabo de forma satisfactoria la sincronizacion de repositorios.
     */
    this->CalcularEsquemaTrabajo();
    
    /* Se ejecuta el proceso de trabajo.
     */
    OperacionSecuencial::ejecutar();
    
}

void OperacionSincronizacionArchivosNuevos::CalcularEsquemaTrabajo(){
    
    this->LimpiarOperaciones();
    
    this->CalcularEsquemaTrabajoArchivosAPublicar();
    
    this->CalcularEsquemaTrabajoArchivosADescargar();
}

SetRepoItem OperacionSincronizacionArchivosNuevos::getArchivosADescargar(){
    
    SetRepoItem items;
    
    RepoItem* itemLocal = (*_repositorioLocal)->Primero();
    
    while (NULL != itemLocal)
    {
        if (itemLocal->GetEstado() == ARCHIVO_A_DESCARGAR)
        {
            items.push_back(itemLocal);
        }
        
        itemLocal = (*_repositorioServidor)->Siguiente(itemLocal);
    }
    
    return items;
}

SetRepoItem OperacionSincronizacionArchivosNuevos::getArchivosAPublicar(){
    
    SetRepoItem items;
    RepoItem* item = (*_repositorioLocal)->Primero();
    
    while (item != NULL)
    {
        if (ARCHIVO_A_PUBLICAR == item->GetEstado())
        {
            items.push_back(item);
        }
        item = (*_repositorioLocal)->Siguiente(item);
    }
    
    return items;
}

void OperacionSincronizacionArchivosNuevos::CalcularEsquemaTrabajoArchivosADescargar(){
 
    // Configura el esquema de trabajo de descarga de archivos nuevos desde el servidor.

    SetRepoItem archivosADescargar = this->getArchivosADescargar();
    SetRepoItemIterator itADescargar = archivosADescargar.begin();

    while (itADescargar < archivosADescargar.end())
    {
        this->AgregarOperacion
        (
            (Operacion*) new OperacionDescargaArchivo 
                (
                  TokenFactory::Crear()
                , _fileService
                , (*_repositorioLocal)
                , (*itADescargar)->GetFilename()
                , (*itADescargar)->GetVersion()
                )
        );
        
        itADescargar++;
    }
    
    archivosADescargar.clear();
}

void OperacionSincronizacionArchivosNuevos::CalcularEsquemaTrabajoArchivosAPublicar(){
 
    // Configura el esquema de trabajo de carga de archivos desde el cliente.
    
    vector<RepoItem*> archivosAPublicar = this->getArchivosAPublicar();
    vector<RepoItem*>::iterator itArchivosAPublicar = archivosAPublicar.begin();
    
    while (itArchivosAPublicar < archivosAPublicar.end())
    {
        this->AgregarOperacion
        (
            (Operacion*) new OperacionCargaArchivo 
            (
              TokenFactory::Crear()
            , _fileService
            , (*_repositorioLocal)
            , (*itArchivosAPublicar)->GetFilename()
            )
        );
        
        itArchivosAPublicar++;
    }
    
    archivosAPublicar.clear();
}